package com.kly.user.traffic;

import cn.hutool.core.net.NetUtil;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.fqgj.common.utils.CollectionUtils;
import com.jsoniter.output.JsonStream;
import com.kly.user.db.dao.StatsTrafficDao;
import com.kly.user.db.dao.TrafficChatterPoolDao;
import com.kly.user.db.dao.UserTrafficAssignLogDao;
import com.kly.user.db.entity.UserTrafficAssignLogEntity;
import com.robert.vesta.util.IdUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;


/**
 * 流量分配策略
 */

@Service
@Slf4j
public class UserTrafficAssignTask {

    @NacosValue(value = "${likeBackMaxCountV1:10}", autoRefreshed = true)
    private Integer maxCountForLikeBack;

    @NacosValue(value = "${lastLikeBackTillNowMinsMinimum:5}", autoRefreshed = true)
    private Integer lastLikeBackTillNowMinsMinimum;


    @NacosValue(value = "${wlmMaxCountV1:5}", autoRefreshed = true)
    private Integer wlmMaxCountV1;

    @NacosValue(value = "${lastWlmTillNowMinsMinimum:5}", autoRefreshed = true)
    private Integer lastWlmTillNowMinsMinimum;

    @NacosValue(value = "${forceMatchMaxCountV1:5}", autoRefreshed = true)
    private Integer forceMatchMaxCountV1;
    @NacosValue(value = "${allowSystemToGiveTrafficMinGap:2}", autoRefreshed = true)
    private Integer allowSystemToGiveTrafficMinGap;

    @NacosValue(value = "${lastForceMatchTillNowMinsMinimum:5}", autoRefreshed = true)
    private Integer lastForceMatchTillNowMinsMinimum;

    @Autowired
    private OfflinePolicy offlinePolicy;

    @Autowired
    private OnlinePolicy2 onlinePolicy2;

    @Autowired
    private UserTrafficAssignLogDao userTrafficAssignLogDao;

    @Autowired
    private StatsTrafficDao statsTrafficDao;


    @NacosValue(value = "${task.job.executor.ip}", autoRefreshed = true)
    private String taskJobExecutor;
    @NacosValue(value = "${newPolicyUserClientEngineSwitchOpen:false}", autoRefreshed = true)
    private boolean newPolicyUserClientEngineSwitchOpen;

    private String localIP = NetUtil.getLocalhostStr();

    @Scheduled(fixedDelay = 1000 * 60)
    public void run() {
        log.info("==TrafficAssignTask 开始  ==");
        if (!newPolicyUserClientEngineSwitchOpen) {
            log.info("==TrafficAssignTask 开关未打开  ==");
            return;
        }

        if (!taskJobExecutor.contains(localIP)) {
            log.info("=============TrafficAssignTask 当前机器IP不允许执行任务, currentLocalAddress:{}, onlyExecuteTaskIn:{}", localIP, taskJobExecutor);
            return;
        }


        List<UserActionsVariable> onlineUsersWithVariables = getOnlineUsersWithVariables();
        if (CollectionUtils.isEmpty(onlineUsersWithVariables)) {
            log.info("==TrafficAssignTask 找不到用户数据  ==");
            return;
        }

        log.info("==TrafficAssignTask 找到用户数据  ==,size:{}", onlineUsersWithVariables.size());

        String versionNo = IdUtils.genId() + "";
        Map<String, GavenTraffic> trafficGavenAlreadyMap = getTrafficGavenAlready().stream().collect(Collectors.toMap(GavenTraffic::getUserCode, traffic -> traffic));

        for (UserActionsVariable onlineUsersWithVariable : onlineUsersWithVariables) {
            String userCode = onlineUsersWithVariable.getUserCode();
            log.info("==TrafficAssignTask 开始生成数据  ==,userCode:{},hasData:{}", userCode, trafficGavenAlreadyMap.containsKey(userCode));
            if (!trafficGavenAlreadyMap.containsKey(userCode)) {
                log.info("==TrafficAssignTask 开始生成数据 当前在线用户没有已分配数据 ==,userCode:{},hasData:{}", userCode, trafficGavenAlreadyMap.containsKey(userCode));
                continue;
            }
            NewTraffic newTraffic = giveTraffic(onlineUsersWithVariable, trafficGavenAlreadyMap.get(userCode));
            UserTrafficAssignLogEntity userTrafficAssignLogEntity = new UserTrafficAssignLogEntity().setUserCode(newTraffic.getUserCode()).setPlanToAssignType(newTraffic.getPlanType().getCode()).setFinalAssignType(newTraffic.getFinalType().getCode()).setReason(newTraffic.getReason()).setVersionNo(versionNo)

                    .setTodayTotalMatchCnt(newTraffic.getGavenTraffic().getTodayMatchCnt()).setWlmCnt(newTraffic.getGavenTraffic().getGetWlmCount()).setLikeBackCnt(newTraffic.getGavenTraffic().getGetLikeBackCount()).setForceMatchCnt(newTraffic.getGavenTraffic().getGetForceConnectCount())

                    .setRegisterMins(onlineUsersWithVariable.getRegisterMins()).setVipValid(onlineUsersWithVariable.getMemberStatus()).setOnlineModelCnt(onlineUsersWithVariable.getOnlineModelCnt()).setAssignStatus(0);

            userTrafficAssignLogDao.insert(userTrafficAssignLogEntity);
        }

    }


    //获取用户相关数据
    private List<UserActionsVariable> getOnlineUsersWithVariables() {
        return statsTrafficDao.getUserVariables();
    }

    private List<GavenTraffic> getTrafficGavenAlready() {
        List<GavenTraffic> todayTrafficData = statsTrafficDao.getTodayTrafficData();
        log.info("==TrafficAssignTask todayTrafficData 开始==,size:{}", todayTrafficData.size());

        return todayTrafficData;
    }

    //判断用户是否缺流量
    private NewTraffic giveTraffic(UserActionsVariable actionsVariable, GavenTraffic gavenTraffic) {
        NewTraffic newTraffic = new NewTraffic();
        String userCode = actionsVariable.getUserCode();
        log.info("==TrafficAssignTask 当前用户流量下发流程 开始==,userCode:{}", userCode);
        newTraffic.setUserCode(userCode).setGavenTraffic(gavenTraffic);
        log.info("==TrafficAssignTask 当前系统已下发的流量==,userCode:{},data:{}", userCode, JsonStream.serialize(gavenTraffic));

        UserTrafficJudgeEngine judgeEngine = new UserTrafficJudgeEngine(actionsVariable);
        if (judgeEngine.isOnline()) {
            log.info("==TrafficAssignTask 用户在线==,userCode:{}", userCode);

            if (!gavenTraffic.allowSystemToGiveTraffic(allowSystemToGiveTrafficMinGap)) {
                return newTraffic.setPlanType(TrafficActionTypeEnum.NO_TRAFFIC).setFinalType(getFinalTrafficType(actionsVariable, gavenTraffic, TrafficActionTypeEnum.NO_TRAFFIC)).setReason("距离上次下发流量的事件太近");
            }

            if (!judgeEngine.registerLongEnough()) {
                log.info("==TrafficAssignTask 注册时间太短 不打扰用户==,userCode:{},mins:{}", userCode, actionsVariable.getRegisterMins());
                return newTraffic.setPlanType(TrafficActionTypeEnum.NO_TRAFFIC).setFinalType(getFinalTrafficType(actionsVariable, gavenTraffic, TrafficActionTypeEnum.NO_TRAFFIC)).setReason("注册时间太短，暂不打扰用户");
            }

            //不管用户在做什么，我们只需要判断用户当前的聊天状态，用户无人可聊，用户能聊的人数太少，用户想聊的人太少，没人回复用户
            if (judgeEngine.isChatting() && judgeEngine.boughtPPVIn2MINS()) {
                log.info("==TrafficAssignTask 用户正在聊天，而且购买了ppv，不打扰==,userCode:{}", userCode);
                return newTraffic.setPlanType(TrafficActionTypeEnum.NO_TRAFFIC).setFinalType(getFinalTrafficType(actionsVariable, gavenTraffic, TrafficActionTypeEnum.NO_TRAFFIC)).setReason("用户正在聊天，而且购买了ppv，不打扰");
            }

            if (!judgeEngine.hasLikedModel()) {
                log.info("==TrafficAssignTask 用户没有喜欢的model，随机挑选一种方式，让用户开聊==,userCode:{}", userCode);
                return newTraffic.setPlanType(TrafficActionTypeEnum.WLM).setFinalType(getFinalTrafficType(actionsVariable, gavenTraffic, TrafficActionTypeEnum.WLM)).setReason("没有喜欢的model,发送wlm");
            }
            if (!judgeEngine.hasEnoughOnlineUserToChat()) {
                log.info("==TrafficAssignTask 用户的在线列表里面人数太少,优先下发likeback==,userCode:{}", userCode);
                return newTraffic.setPlanType(TrafficActionTypeEnum.LIKE_BACK_USER).setFinalType(getFinalTrafficType(actionsVariable, gavenTraffic, TrafficActionTypeEnum.LIKE_BACK_USER)).setReason("在线的model人数太少，先使用likeback");
            }

            if (!judgeEngine.hasWillingChatEnough()) {
                log.info("==TrafficAssignTask 用户的在线列表里面人数太少,优先下发likeback==,userCode:{}", userCode);
                return newTraffic.setPlanType(TrafficActionTypeEnum.LIKE_BACK_USER).setFinalType(getFinalTrafficType(actionsVariable, gavenTraffic, TrafficActionTypeEnum.LIKE_BACK_USER)).setReason("用户貌似不太中意在聊的主播");
            }

            if (!judgeEngine.hasChatterServeInTime()) {
                log.info("==TrafficAssignTask 用户给在线的model发送消息，但是model的回复不及时==,userCode:{}", userCode);
                giveChatterNote(userCode);
                return newTraffic.setPlanType(TrafficActionTypeEnum.NOTE_CHATTER).setFinalType(getFinalTrafficType(actionsVariable, gavenTraffic, TrafficActionTypeEnum.NOTE_CHATTER)).setReason("给主播提醒，做好承接");
            }

            log.info("==TrafficAssignTask 不符合条件，随机挑选一种方式，让用户开聊==,userCode:{}", userCode);
            return newTraffic.setPlanType(TrafficActionTypeEnum.RANDOM_WAY).setFinalType(getFinalTrafficType(actionsVariable, gavenTraffic, TrafficActionTypeEnum.RANDOM_WAY)).setReason("没有喜欢的model,随机挑选一种方式，让用户开聊");
        } else {
            log.info("==TrafficAssignTask 离线用户暂不做处理==,userCode:{}", userCode);
        }

        log.info("==TrafficAssignTask 当前用户流量下发流程 结束==,userCode:{}", userCode);
        return newTraffic.setPlanType(TrafficActionTypeEnum.WLM).setFinalType(getFinalTrafficType(actionsVariable, gavenTraffic, TrafficActionTypeEnum.WLM)).setReason("策略跳过，不发送流量");
    }

    //确定给用户下发什么样的流量,wlm,likeback,强制建联，主播通知


    private TrafficActionTypeEnum getFinalTrafficType(UserActionsVariable actionsVariable, GavenTraffic gavenTraffic, TrafficActionTypeEnum priorityType) {
        if (priorityType == TrafficActionTypeEnum.NO_TRAFFIC || priorityType == TrafficActionTypeEnum.NOTE_CHATTER) {
            return priorityType;
        }


        if (priorityType == TrafficActionTypeEnum.RANDOM_WAY) {
            TrafficActionTypeEnum[] allValues = TrafficActionTypeEnum.values();

            // 剔除掉两种枚举值
            List<TrafficActionTypeEnum> allowedValues = new ArrayList<>(Arrays.asList(allValues));
            allowedValues.remove(TrafficActionTypeEnum.RANDOM_WAY);
            allowedValues.remove(TrafficActionTypeEnum.NO_TRAFFIC);
            allowedValues.remove(TrafficActionTypeEnum.NOTE_CHATTER);

            // 创建一个 Random 对象
            Random random = new Random();

            // 从允许的枚举值中随机选择一个值
            priorityType = allowedValues.get(random.nextInt(allowedValues.size()));

        }


        boolean fcCheckPass = gavenTraffic.forceConnectRateCheckPass(lastForceMatchTillNowMinsMinimum, forceMatchMaxCountV1);
        boolean wlmCheckPass = gavenTraffic.wlmRateCheckPass(lastWlmTillNowMinsMinimum, wlmMaxCountV1);
        boolean likebackRateCheckPass = gavenTraffic.likebackRateCheckPass(actionsVariable.getTodayRemainLikeCnt(), lastLikeBackTillNowMinsMinimum, maxCountForLikeBack);

        if (TrafficActionTypeEnum.WLM == priorityType) {
            if (wlmCheckPass) {
                return priorityType;
            } else if (likebackRateCheckPass) {
                return TrafficActionTypeEnum.LIKE_BACK_USER;
            } else if (fcCheckPass) return TrafficActionTypeEnum.FORCE_CONNECT;
        }

        if (TrafficActionTypeEnum.LIKE_BACK_USER == priorityType) {
            if (likebackRateCheckPass) {
                return priorityType;
            } else if (fcCheckPass) {
                return TrafficActionTypeEnum.FORCE_CONNECT;
            } else if (wlmCheckPass) return TrafficActionTypeEnum.WLM;
        }

        if (TrafficActionTypeEnum.FORCE_CONNECT == priorityType) {
            if (fcCheckPass) {
                return priorityType;
            } else if (likebackRateCheckPass) {
                return TrafficActionTypeEnum.LIKE_BACK_USER;
            } else if (wlmCheckPass) return TrafficActionTypeEnum.WLM;
        }

        return TrafficActionTypeEnum.NO_TRAFFIC;
    }

    private void giveChatterNote(String userCode) {

    }

    private String findTargetModel(String userCode, TrafficActionTypeEnum trafficActionTypeEnum) {

        return null;
    }

    @Autowired
    private TrafficChatterPoolDao trafficChatterPoolDao;

    @Scheduled(fixedDelay = 1000 * 60)
    public void createChatterPool() {
        log.info("==createChatterPool 开始  ==");
        if (!newPolicyUserClientEngineSwitchOpen) {
            log.info("==createChatterPool 开关未打开  ==");
            return;
        }

        if (!taskJobExecutor.contains(localIP)) {
            log.info("=============createChatterPool 当前机器IP不允许执行任务, currentLocalAddress:{}, onlyExecuteTaskIn:{}", localIP, taskJobExecutor);
            return;
        }
        trafficChatterPoolDao.createChatterPool();
        log.info("==createChatterPool 更新完成  ==");
    }

}
